#include "MessageParser.h"

Message MessageParser::parseRequestMessage(const string& strmessage) {
	xmlDocPtr doc = xmlReadMemory(strmessage.c_str(), strmessage.length(),
			NULL, NULL, 0);
	if (doc == NULL)
		throw ParsingException("Message not parsed successfully");
	xmlNodePtr cur;
	cur = xmlDocGetRootElement(doc);
	if (cur == NULL) {
		xmlFreeDoc(doc);
		throw ParsingException("Empty message");
	}
	if (xmlStrcmp(cur->name, BAD_CAST "root")) {
		xmlFreeDoc(doc);
		throw ParsingException("Invalid root node");
	}
	Message message;
	cur = cur->xmlChildrenNode;
	while (cur != NULL) {
		if (!xmlStrcmp(cur->name, BAD_CAST "version"))
			if (cur->xmlChildrenNode != NULL)
				message.version = atoi((const char*) xmlNodeListGetString(doc,
						cur->xmlChildrenNode, 1));
			else
				throw ParsingException("Invalid message format. After version");
		else if (!xmlStrcmp(cur->name, BAD_CAST "request-list")) {
			message.messageType = REQUEST_LIST;
			xmlNodePtr child = cur->xmlChildrenNode;
			if (child != NULL and !xmlStrcmp(child->name,
					BAD_CAST "list-length"))
				message.list_length = atoi((const char*) xmlNodeListGetString(
						doc, child->xmlChildrenNode, 1));
			else
				throw ParsingException(
						"Invalid message format. After request-list");
		} else if (!xmlStrcmp(cur->name, BAD_CAST "submit-rating")) {
			message.messageType = SUBMIT_RATING;
			xmlNodePtr child = cur->xmlChildrenNode;
			if (child != NULL and child->next != NULL) {
				if (!xmlStrcmp(child->name, BAD_CAST "content-id")
						and !xmlStrcmp(child->next->name, BAD_CAST "rating"))
					message.rating = std::make_pair(atoi(
							(const char*) xmlNodeListGetString(doc,
									child->xmlChildrenNode, 1)), atoi(
							(const char*) xmlNodeListGetString(doc,
									child->next->xmlChildrenNode, 1)));
				else
					throw ParsingException(
							"Invalid message format. After content");
			}
		} else if (!xmlStrcmp(cur->name, BAD_CAST "request-profile"))
			message.messageType = REQUEST_PROFILE;
		else if (!xmlStrcmp(cur->name, (const xmlChar*) "response-list")
				or !xmlStrcmp(cur->name, BAD_CAST "response-profile"))
			continue;
		else
			throw ParsingException("Invalid message format");
		cur = cur->next;
	}
	xmlFreeDoc(doc);

	return message;
}

string MessageParser::parseResponseMessage(
		const multimap<string, string>& contents) {
	xmlNodePtr root, request, content, genre, program;
	xmlDocPtr doc;
	xmlChar* xmlbuff;
	int buffersize;

	doc = xmlNewDoc(BAD_CAST "1.0");
	root = xmlNewNode(NULL, BAD_CAST "root");
	xmlDocSetRootElement(doc, root);
	xmlNewChild(root, NULL, BAD_CAST "version", BAD_CAST "1.0");
	request = xmlNewChild(root, NULL, BAD_CAST "response-list", NULL);
	multimap<string, string>::const_iterator c = contents.begin();
	while (c != contents.end()) {
		content = xmlNewChild(request, NULL, BAD_CAST "content", NULL);
		genre = xmlNewChild(content, NULL, BAD_CAST "genre", NULL);
		xmlNodeSetContent(genre, BAD_CAST c->first.c_str());
		program = xmlNewChild(content, NULL, BAD_CAST "program", NULL);
		xmlNodeSetContent(program, BAD_CAST c->second.c_str());
		c++;
	}
	xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
	string xml = (const char*) xmlbuff;
	xmlFree(xmlbuff);
	xmlFreeDoc(doc);

	return xml;
}
